package org.skydiveapp;

import java.io.File;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.skydiveapplibrary.ui.ImageAdapter;
import org.skydiveapplibrary.ui.ImageGrid;
import org.skydiveapplibrary.ui.InterfaceManager;
import org.skydiveapplibrary.R;
import org.skydiveapplibrary.data.AltitudeUnit;
import org.skydiveapplibrary.data.Constants;
import org.skydiveapplibrary.data.FreefallProfileType;
import org.skydiveapplibrary.data.LogEntry;
import org.skydiveapplibrary.data.LogEntryImage;
import org.skydiveapplibrary.data.LogEntryImageType;
import org.skydiveapplibrary.repository.AircraftRepository;
import org.skydiveapplibrary.repository.LocationRepository;
import org.skydiveapplibrary.repository.LogEntryRepository;
import org.skydiveapplibrary.repository.RigRepository;
import org.skydiveapplibrary.repository.SkydiveTypeRepository;
import org.skydiveapplibrary.ui.FormatUtility;
import org.skydiveapplibrary.ui.ImageManager;
import org.skydiveapplibrary.ui.NumberDialog;
import org.skydiveapplibrary.ui.NumberDialog.OnNumberSetListener;
import org.skydiveapplibrary.util.FileManager;
import org.skydiveapplibrary.util.FreefallTimeCalculator;

import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;

public class LogEntryEditFragment extends SherlockFragment
{
	onLogEntryEditStatusChangedListener mListener;
	 
	 public interface onLogEntryEditStatusChangedListener
	 {
	        public void onLogEntryEditStatusChanged(int status);
	 }
	 
	 // activity request codes
	 private static final int REQUEST_SELECT_SKYDIVE_TYPE = 0;
	 private static final int REQUEST_SELECT_LOCATION = 1;
	 private static final int REQUEST_SELECT_AIRCRAFT = 2;
	 private static final int REQUEST_SELECT_GEAR = 3;
	 private static final int REQUEST_DIAGRAM = 4;
	 private static final int REQUEST_ADD_PHOTO = 5;
	 private static final int REQUEST_VIEW_PHOTO = 6;
	 private static final int REQUEST_NOTES = 7;
	 
	 // image size
	 private int IMAGE_WIDTH = 200;
	 private int IMAGE_HEIGHT = 200;
	
	// repositories
	private LogEntryRepository repository;
	private LocationRepository locRepository;
	private AircraftRepository aircraftRepository;
	private RigRepository rigRepository;
	private SkydiveTypeRepository skydiveTypeRepository;
	
	// image mgr
	private ImageManager imageManager;
	private ImageAdapter imageAdapter;
	private FileManager fileManager;
	
	// data
	private boolean isEdit = false;
	private boolean isCopy = false;
	private boolean isUpdated = false;
	private boolean isSaved = false;
	private LogEntry logEntry;
	private LogEntryImage currentEditedImage;
	private int logEntryId;
	private boolean isDualDisplay = false;
		
	private static final int REQUEST_CLOSE = 10;
	private static final int REQUEST_UPDATE = 20;
	
	private static final int REPLY_CLOSED = 10;
	private static final int REPLY_UPDATEABLE = 20;
	
	private int requestedAction = 0;

	private DialogInterface.OnClickListener deleteConfirmListener = new DialogInterface.OnClickListener()
	{
		@Override
		public void onClick(DialogInterface arg0, int arg1)
		{
			delete();
		}
	};
	private OnClickListener estimateFFTimeListener = new OnClickListener()
	{
		@Override
		public void onClick(View v)
		{
			estimateFreefallTime();
		}
	};
	private OnClickListener notesEditListener = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{
			Intent intent = new Intent(getActivity(), NotesEditActivity.class);
            intent.putExtra(Constants.EXTRA_NOTES, logEntry.getNotes());
            intent.putExtra(Constants.EXTRA_SEMI_TRANSPARENT_THEME, true);
            startActivityForResult(intent, REQUEST_NOTES);
		}
	};
	private OnClickListener locationEditListener = new OnClickListener()
	{
		@Override
        public void onClick(View view)
        {
                Intent intent = new Intent(getActivity(), LocationSelectListActivity.class);
                if (logEntry.getLocation() != null)
                {
                        intent.putExtra(Constants.EXTRA_LOCATION_ID, logEntry.getLocation().getId());
                }
                startActivityForResult(intent, REQUEST_SELECT_LOCATION);
        }
	};
	private OnClickListener jumpNumberEditListener = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{
			showJumpNumberDialog();
		}
	};
	private OnNumberSetListener jumpNumberSetListener = new OnNumberSetListener()
	{
		@Override
		public void onNumberSet(NumberDialog dialog, int number)
		{
			updateJumpNumber(number);
		}
	};
	private OnClickListener dateEditListener = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{
			showDateDialog();
		}
	};
	private OnDateSetListener dateSetListener = new OnDateSetListener()
	{
		@Override
		public void onDateSet(DatePicker dialog, int year, int month, int day)
		{
			Calendar cal = Calendar.getInstance();
			cal.set(year, month, day);
			updateDate(cal.getTime());
		}
	};
	private OnClickListener aircraftEditListener = new OnClickListener()
	{
		@Override
        public void onClick(View view)
        {
	        Intent intent = new Intent(getActivity(), AircraftSelectListActivity.class);
	        if (logEntry.getAircraft() != null)
	        {
	                intent.putExtra(Constants.EXTRA_AIRCRAFT_ID, logEntry.getAircraft().getId());
	        }
	        startActivityForResult(intent, REQUEST_SELECT_AIRCRAFT);
        }
	};
	private OnClickListener gearEditListener = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{		
			Intent intent = new Intent(getActivity(), GearListSelectActivity.class);
            intent.putExtra(Constants.EXTRA_SELECTED_RIG_IDS, (Serializable)getSelectedRigIds());
            startActivityForResult(intent, REQUEST_SELECT_GEAR);
		}
	};
	private OnClickListener skydiveTypeEditListener = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{			
			Intent intent = new Intent(getActivity(), SkydiveTypeSelectListActivity.class);
            if (logEntry.getSkydiveType() != null)
            {
            	intent.putExtra(Constants.EXTRA_SKYDIVE_TYPE_ID, logEntry.getSkydiveType().getId());
            }
            startActivityForResult(intent, REQUEST_SELECT_SKYDIVE_TYPE);
		}
	};
	private OnClickListener diagramAddListsner = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{	
			// clear currently edited
			currentEditedImage = null;
			
			// launch diagram editor
			Intent intent = new Intent(getActivity(), LogEntryDiagramActivity.class);
            startActivityForResult(intent, REQUEST_DIAGRAM);
		}
	};
	private OnClickListener photoAddListsner = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{	
			// clear currently edited
			currentEditedImage = null;
						
			// launch photo picker
			Intent intent = new Intent(Intent.ACTION_PICK);
			intent.setType("image/*");
			startActivityForResult(intent, REQUEST_ADD_PHOTO);
		}
	};
	private OnClickListener imageEditListener = new OnClickListener()
	{
		@Override
		public void onClick(View view)
		{
			// set currently edited
			currentEditedImage = (LogEntryImage)view.getTag();
			if (currentEditedImage.getImageType() == LogEntryImageType.Diagram)
			{
				Intent intent = new Intent(getActivity(), LogEntryDiagramActivity.class);
	            intent.putExtra(Constants.EXTRA_DIAGRAM_FILENAME, currentEditedImage.getFilename());
	            startActivityForResult(intent, REQUEST_DIAGRAM);
			}
			else
			{
				Intent intent = new Intent(getActivity(), LogEntryPhotoActivity.class);
	            intent.putExtra(Constants.EXTRA_PHOTO, currentEditedImage.getFilename());
	            startActivityForResult(intent, REQUEST_VIEW_PHOTO);
			}
		}
	};
	
	private OnClickListener signatureViewListener = new OnClickListener()
	{
		public void onClick(View view)
		{
			// create alert dialog
			AlertDialog.Builder builder = new AlertDialog.Builder(
					new ContextThemeWrapper(getActivity(), R.style.DialogStyle));
			
			builder.setIcon(R.drawable.ic_menu_sign);
			builder.setTitle(logEntry.getSignature().getLicense());
			
			ImageView siImage = new ImageView(getActivity());
			siImage.setBackgroundColor(Color.WHITE);

			siImage.setImageBitmap(imageManager.decodeToScreenSize(logEntry.getSignature().getFilename()));
			siImage.setAdjustViewBounds(true);
			builder.setView(siImage);
			
			builder.setNegativeButton(R.string.done_button, null);
				
			AlertDialog dialog = builder.create();
			// show dialog
			dialog.show();
		}
	};
	
	
	public static LogEntryEditFragment newInstance(Bundle args) 
	{
		LogEntryEditFragment f = new LogEntryEditFragment();
		f.setArguments(args);
		return f;
	}
	
    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
        // Check that the container activity has implemented the callback interface
        try
        {
            mListener = (onLogEntryEditStatusChangedListener) activity;
        }
        catch (ClassCastException e)
        {
            throw new ClassCastException(activity.toString() 
                    + " must implement onRequestReplyListener");
        }
    }

	/** Called when the fragment is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		View logEntryLeftView = getActivity().findViewById(R.id.leftFrame);
		isDualDisplay = !(logEntryLeftView == null);
		
		repository = new LogEntryRepository(getActivity());
		locRepository = new LocationRepository(getActivity());
		aircraftRepository = new AircraftRepository(getActivity());
		rigRepository = new RigRepository(getActivity());
		skydiveTypeRepository = new SkydiveTypeRepository(getActivity());
		imageManager = new ImageManager(getActivity());
		fileManager = new FileManager(getActivity());
		
		if (imageAdapter == null)
			imageAdapter = new ImageAdapter(getActivity());
		
		// set isSaved, isEdit, and isCopy flag
		Bundle extras;
		if (savedInstanceState != null)
			extras = savedInstanceState;
		else
			extras = isDualDisplay ? getArguments() : getActivity().getIntent().getExtras();
		
		// load data
		loadData(extras);
		
		setHasOptionsMenu(true);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
	    		Bundle savedInstanceState)
	{	
	    // Inflate the layout for this fragment
	    View view = inflater.inflate(R.layout.log_entry_edit_view, container, false);
	    
		// init ui
		initializeUI(view);
		
	    return view;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent intent)
	{
		if (resultCode == Activity.RESULT_OK)
			isUpdated = true;
			
		if (requestCode == REQUEST_SELECT_SKYDIVE_TYPE && resultCode == Activity.RESULT_OK)
		{
			int id = intent.getIntExtra(Constants.EXTRA_SKYDIVE_TYPE_ID, -1);
			updateSkydiveType(id);
		}
		else if (requestCode == REQUEST_SELECT_LOCATION && resultCode == Activity.RESULT_OK)
		{
			int id = intent.getIntExtra(Constants.EXTRA_LOCATION_ID, -1);
			updateLocation(id);
		}
		else if (requestCode == REQUEST_SELECT_AIRCRAFT && resultCode == Activity.RESULT_OK)
		{
			int id = intent.getIntExtra(Constants.EXTRA_AIRCRAFT_ID, -1);
			updateAircraft(id);
		}
		else if (requestCode == REQUEST_SELECT_GEAR && resultCode == Activity.RESULT_OK)
		{
			List<Integer> ids = (List<Integer>) intent.getSerializableExtra(Constants.EXTRA_SELECTED_RIG_IDS);
			updateRig(ids);
		}
		else if (requestCode == REQUEST_NOTES && resultCode == Activity.RESULT_OK)
		{
			String notes = intent.getStringExtra(Constants.EXTRA_NOTES);
			updateNotes(notes);
		}
		else if (requestCode == REQUEST_DIAGRAM && resultCode == Activity.RESULT_OK)
		{
			// get image data
			String fileName = intent.getStringExtra(Constants.EXTRA_DIAGRAM_FILENAME);
						
			boolean deleteDiagram = intent.getBooleanExtra(Constants.EXTRA_DIAGRAM_DELETE, false);
			
			// deleting current image
			if (deleteDiagram && currentEditedImage != null)
			{
				logEntry.getImages().remove(currentEditedImage);
			}
			
			// updating current image
			if (!deleteDiagram && currentEditedImage != null)
			{
				currentEditedImage.setFilename(fileName);
				currentEditedImage.setMD5(fileName.replace(".jpg", ""));
			}
			
			// adding new image
			if (!deleteDiagram && currentEditedImage == null)
			{
				// create/add image
				LogEntryImage newImage = new LogEntryImage();
				newImage.setFilename(fileName);
				newImage.setMD5(fileName.replace(".jpg", ""));
				newImage.setImageType(LogEntryImageType.Diagram);
				logEntry.getImages().add(newImage);
			}
			
			// re-init images
			initImagesUI();
		}
		else if (requestCode == REQUEST_VIEW_PHOTO && resultCode == Activity.RESULT_OK)
		{
			boolean delete = intent.getBooleanExtra(Constants.EXTRA_PHOTO_DELETE, false);
			
			// deleting current image
			if (delete && currentEditedImage != null)
			{
				logEntry.getImages().remove(currentEditedImage);
			}
			
			// re-init images
			initImagesUI();
		}
		else if (requestCode == REQUEST_ADD_PHOTO && resultCode == Activity.RESULT_OK)
		{
			// get image data
			Uri imageUri = intent.getData();
					
			File file = null;
			
			if (imageUri.toString().contains("android.gallery3d.provider/picasa/"))
			{
				file = fileManager.writePicasaFileToStorage(imageUri);
				if (file == null)
				{
					Toast.makeText(getActivity(), getString(R.string.picasa_download_error)
							, Toast.LENGTH_LONG).show();
					return;
				}
			}
			else
			{
				file = fileManager.copyToStorageDir(imageUri);
				if (file == null)
				{
					Toast.makeText(getActivity(), getString(R.string.file_copy_error)
							, Toast.LENGTH_LONG).show();
					return;
				}
			}
			
			if (file.getName() != null)
			{	
				LogEntryImage newImage = new LogEntryImage();
				newImage.setImageType(LogEntryImageType.Photo);
				newImage.setFilename(file.getName());
				newImage.setMD5(file.getName().replace(".jpg", ""));
				
				logEntry.getImages().add(newImage);
			}
			
			// re-init images
			initImagesUI();
		}
	}
	
	@Override
	public void onPause()
	{
		super.onPause();
		isUpdated = isUpdated ? true : checkForChanges();
		commitChangesToLogEntry();
	}
	
	@Override
	public void onResume()
	{
		super.onResume();
		
		// After screen rotation the fragment can be briefly
		// visible before the main activity removes it.  
		// This hides it so the user is unaware.
		if (!isDualDisplay && getActivity().findViewById(R.id.logEntryEditActivityLayout) == null)
			getView().setVisibility(View.GONE);
		
		ImageGrid imageGrid = (ImageGrid) getActivity().findViewById(R.id.imageGrid);
		imageGrid.getViewTreeObserver().addOnGlobalLayoutListener(
				new ViewTreeObserver.OnGlobalLayoutListener()
				{
					public void onGlobalLayout()
					{
						 // When we get here, the size of the frame view is known.
						 // Use those dimensions to set the width of the image size.
						if (imageAdapter.getImageSize() == 0)
						{
							imageAdapter.setImageSize(imageAdapter.getImageSize());
							if (getView() != null)
								initImagesUI();
						}
					}
				});
		
		if (imageAdapter.getImageSize() > 0)
		{
			initImagesUI();
		}

		// update fields
		updateFields();
	}
	
	
	private void loadData(Bundle extras)
	{	
		logEntryId = extras.getInt(Constants.EXTRA_LOG_ENTRY_ID, 0);
		isEdit = extras.containsKey(Constants.EXTRA_LOG_ENTRY_ID);
		isCopy = extras.containsKey(Constants.EXTRA_LOG_ENTRY_COPY);
		isSaved = extras.containsKey(Constants.EXTRA_LOG_ENTRY_SAVED);
		isUpdated = extras.containsKey(Constants.EXTRA_LOG_ENTRY_UPDATED);
		
		// determine load vs. add vs. edit
		if (isSaved)
		{
			//load from application
			logEntry = ((SkydiveApplication) getActivity().getApplication()).getStoredLogEntry();
		}
		else if (isEdit)
		{
			// editing
			logEntry = repository.getLogEntry(logEntryId);
		}
		else if (isCopy)
		{
			// create new using last logs fields
			logEntry = repository.getNewFromLastEntry();
		}
		else
		{
			// adding
			logEntry = new LogEntry();
			// set defaults
			repository.setDefaults(logEntry);
		}
		
		//reset data
		isSaved = false;
	}
	
	private void initializeUI(View view)
	{
		// set jump number listener
		TextView jumpNumberField = (TextView) view.findViewById(R.id.LogEntryJumpNumberField);
		jumpNumberField.setOnClickListener(jumpNumberEditListener);
		
		// set date listener
		TextView dateField = (TextView) view.findViewById(R.id.LogEntryDateField);
		dateField.setOnClickListener(dateEditListener);

		// set location listener
		TextView locField = (TextView) view.findViewById(R.id.LogEntryLocationField);
		locField.setOnClickListener(locationEditListener);
		
		// set aircraft listener
		TextView airField = (TextView) view.findViewById(R.id.LogEntryAircraftField);
		airField.setOnClickListener(aircraftEditListener);

		// set gear listener
		TextView gearField = (TextView) view.findViewById(R.id.LogEntryGearField);
		gearField.setOnClickListener(gearEditListener);
		
		// set type listener
		TextView typeField = (TextView) view.findViewById(R.id.LogEntryTypeField);
		typeField.setOnClickListener(skydiveTypeEditListener);
		
		// set exit altitude label
		TextView eaLabel = (TextView) view.findViewById(R.id.LogEntryExitAltitudeLabel);
		eaLabel.setText(MessageFormat.format(
				getString(R.string.log_entry_exit_altitude_label_format),
				getString(logEntry.getAltitudeUnit().getResourceId())));
			
		// set deploy altitude label
		TextView daLabel = (TextView) view.findViewById(R.id.LogEntryDeploymentAltitudeLabel);
		daLabel.setText(MessageFormat.format(
				getString(R.string.log_entry_deployment_altitude_label_format),
				getString(logEntry.getAltitudeUnit().getResourceId())));

		// set distance to target label
		TextView dttLabel = (TextView) view.findViewById(R.id.LogEntryDistanceToTargetLabel);
		dttLabel.setText(MessageFormat.format(
				getString(R.string.log_entry_distance_to_target_label_format),
				getString(logEntry.getAltitudeUnit().getResourceId())));
						
		// set notes listener
		TextView nField = (TextView) view.findViewById(R.id.LogEntryNotesField);
		nField.setOnClickListener(notesEditListener);
		
		View estimateFFTimeButton = view.findViewById(R.id.LogEntryEstimateFreefallTimeButton);
		estimateFFTimeButton.setOnClickListener(estimateFFTimeListener);
        
		// set signature listener
		TableLayout siImage = (TableLayout) view.findViewById(R.id.LogEntrySignatureGroup);
		siImage.setOnClickListener(signatureViewListener);
		
		// set add photo button
        Button addPhotoButton = (Button) view.findViewById(R.id.logEntryAddPhotoButton);
        addPhotoButton.setOnClickListener(photoAddListsner);
        
        // set add diagram button
        Button addDiagramButton = (Button) view.findViewById(R.id.logEntryAddDiagramButton);
        addDiagramButton.setOnClickListener(diagramAddListsner);
	}

	private void updateFields()
	{
		// set subtitle text
		String titleText =  isEdit ? 
					getResources().getString(R.string.log_entry_edit_label) : 
					getResources().getString(R.string.log_entry_new_label);
    	
    	InterfaceManager.getInstance().setSubtitleText(getSherlockActivity().getSupportActionBar(),
    													titleText);
		
		// set jump number
		TextView jumpNumberField = (TextView) getView().findViewById(R.id.LogEntryJumpNumberField);
		jumpNumberField.setText(FormatUtility.toNumericString(logEntry.getJumpNumber()));
		
		// set date
		TextView dateField = (TextView) getView().findViewById(R.id.LogEntryDateField);
		dateField.setText(FormatUtility.toDateString(getActivity(), logEntry.getDate()));
		
		// set type
		TextView typeField = (TextView) getView().findViewById(R.id.LogEntryTypeField);
		typeField.setText(logEntry.getSkydiveType() == null ? "" :
			logEntry.getSkydiveType().getName());
		
		// set location
		TextView locField = (TextView) getView().findViewById(R.id.LogEntryLocationField);
		locField.setText(logEntry.getLocation() == null ? "" :
			logEntry.getLocation().getName());
		
		// set aircraft
		TextView airField = (TextView) getView().findViewById(R.id.LogEntryAircraftField);
		airField.setText(logEntry.getAircraft() == null ? "" :
			logEntry.getAircraft().getName());
		
		// set gear
		TextView gearField = (TextView) getView().findViewById(R.id.LogEntryGearField);
		gearField.setText(getGearText());
		
		// init exit altitude
		if (logEntry.getExitAltitude() != null)
		{
			EditText eaField = (EditText) getView().findViewById(R.id.LogEntryExitAltitudeField);
			eaField.setText(FormatUtility.toNumericString(logEntry.getExitAltitude()));
		}
		
		// init deployment altitude
		if (logEntry.getDeploymentAltitude() != null)
		{
			EditText daField = (EditText) getView().findViewById(R.id.LogEntryDeploymentAltitudeField);
			daField.setText(FormatUtility.toNumericString(logEntry.getDeploymentAltitude()));
		}
		
		// set freefall time
		if (logEntry.getFreeFallTimeSeconds() != null)
		{
			EditText ffField = (EditText) getView().findViewById(R.id.LogEntryFreefallTimeField);
			ffField.setText(FormatUtility.toNumericString(logEntry.getFreeFallTimeSeconds()));
		}
		
		// init distance to target
		if (logEntry.getDistanceToTarget() != null)
		{
			EditText dttField = (EditText) getView().findViewById(R.id.LogEntryDistanceToTargetField);
			dttField.setText(FormatUtility.toNumericString(logEntry.getDistanceToTarget()));
		}
		
		// set cutaway
		CheckBox caField = (CheckBox) getView().findViewById(R.id.LogEntryCutawayField);
		caField.setChecked(logEntry.isCutaway());
		
		// set notes
		TextView nField = (TextView) getView().findViewById(R.id.LogEntryNotesField);
		nField.setText(logEntry.getNotes());
		
		// set signature
		View signatureGroup =  getView().findViewById(R.id.LogEntrySignatureGroup);
		if (logEntry.getSignature() == null)
		{
			signatureGroup.setVisibility(View.GONE);
		}
		else
		{
			signatureGroup.setVisibility(View.VISIBLE);
			// set signature image

			ImageView signatureField = (ImageView) getView().findViewById(R.id.LogEntrySignatureField);

			signatureField.setImageBitmap(imageManager.loadToSize(
					logEntry.getSignature().getFilename(),
					IMAGE_WIDTH,
					IMAGE_HEIGHT));
			
			// set license
			TextView licenseField = (TextView) getView().findViewById(R.id.LogEntryLicenseField);
			licenseField.setText(logEntry.getSignature().getLicense());
		}
	}
	
	private void initImagesUI()
	{
		imageAdapter.refreshImages(logEntry.getImages());
		
		ImageGrid imageGrid = (ImageGrid) getActivity().findViewById(R.id.imageGrid);
		imageGrid.removeAllViews();
		imageAdapter.setImageSize(imageGrid.getImageSize());
		
		for (int i = 0; i < imageAdapter.getCount(); i++)
		{
			ImageView imageView = (ImageView) imageAdapter.getView(i, null, imageGrid);
			imageView.setTag(imageAdapter.getItem(i));
			imageView.setOnClickListener(imageEditListener);
			imageGrid.addView(imageView);
		}
	}

	private void estimateFreefallTime()
	{
		// get fields
		EditText exitAltField = (EditText) getView().findViewById(R.id.LogEntryExitAltitudeField);
		EditText deplAltField = (EditText) getView().findViewById(R.id.LogEntryDeploymentAltitudeField);
		
		// get values
		FreefallProfileType freefallProfile =
			(logEntry.getSkydiveType() != null && logEntry.getSkydiveType().getFreefallProfileType() != null) ?
					logEntry.getSkydiveType().getFreefallProfileType() : FreefallProfileType.Horizontal;
		AltitudeUnit altUnit = logEntry.getAltitudeUnit();
		int exitAlt = FormatUtility.fromNumericString(exitAltField.getText().toString());
		int deplAlt = FormatUtility.fromNumericString(deplAltField.getText().toString());
		
		// get estimate
		int estimate = FreefallTimeCalculator.calculateFreefallTime(
				freefallProfile, exitAlt, deplAlt, altUnit);
		
		// update ui
		TextView ffTimeField = (TextView) getView().findViewById(R.id.LogEntryFreefallTimeField);
		ffTimeField.setText(String.valueOf(estimate));
	}
	
	private String getGearText()
	{
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < logEntry.getRigs().size(); i++)
		{
			builder.append(logEntry.getRigs().get(i).getName());
			if (i < logEntry.getRigs().size() - 1)
			{
				builder.append(", ");
			}
		}
		return builder.toString();
	}
	
	private void showJumpNumberDialog()
	{
		// init dialog
		NumberDialog dialog = new NumberDialog(
				new ContextThemeWrapper(getActivity(), R.style.DialogStyle),
				R.string.jump_number_title,
				logEntry.getJumpNumber(),
				jumpNumberSetListener);
		// show dialog
		dialog.show();
	}

	private List<Integer> getSelectedRigIds()
	{
		List<Integer> ids = new ArrayList<Integer>();
		for (int i = 0; i < logEntry.getRigs().size(); i++)
		{
			ids.add(logEntry.getRigs().get(i).getId());
		}
		return ids;
	}
	
	private boolean checkForChanges()
	{
		// check exit altitude
        EditText eaField = (EditText) getView().findViewById(R.id.LogEntryExitAltitudeField);
        String eaString = eaField.getText().toString();
        if (logEntry.getExitAltitude() != null && !logEntry.getExitAltitude().equals(FormatUtility.fromNumericString(eaString)))
        	return true;
        
        // check deployment altitude
        EditText daField = (EditText) getView().findViewById(R.id.LogEntryDeploymentAltitudeField);
        String daString = daField.getText().toString();
        if (logEntry.getDeploymentAltitude() != null && !logEntry.getDeploymentAltitude().equals(FormatUtility.fromNumericString(daString)))
        	return true;
        
        // check freefall time
        EditText ffField = (EditText) getView().findViewById(R.id.LogEntryFreefallTimeField);
        String ffString = ffField.getText().toString();
        if(logEntry.getFreeFallTimeSeconds() != null && !logEntry.getFreeFallTimeSeconds().equals(FormatUtility.fromNumericString(ffString)))
        	return true;
        
        // check distance to target
        EditText dttField = (EditText) getView().findViewById(R.id.LogEntryDistanceToTargetField);
        String dttString = dttField.getText().toString();
        if(logEntry.getDistanceToTarget() != null && !logEntry.getDistanceToTarget().equals(FormatUtility.fromNumericString(dttString)))
        	return true;
        
        // check cutaway
        CheckBox caField = (CheckBox) getView().findViewById(R.id.LogEntryCutawayField);
        if(!logEntry.isCutaway() == caField.isChecked())
        	return true;
        
        return false;
	}
	
	private void commitChangesToLogEntry()
	{
		// set exit altitude
        EditText eaField = (EditText) getView().findViewById(R.id.LogEntryExitAltitudeField);
        String eaString = eaField.getText().toString();
        logEntry.setExitAltitude(FormatUtility.fromNumericString(eaString));
        
        // set deployment altitude
        EditText daField = (EditText) getView().findViewById(R.id.LogEntryDeploymentAltitudeField);
        String daString = daField.getText().toString();
        logEntry.setDeploymentAltitude(FormatUtility.fromNumericString(daString));
        
        // set freefall time
        EditText ffField = (EditText) getView().findViewById(R.id.LogEntryFreefallTimeField);
        String ffString = ffField.getText().toString();
        logEntry.setFreeFallTimeSeconds(FormatUtility.fromNumericString(ffString));

        // set distance to target
        EditText dttField = (EditText) getView().findViewById(R.id.LogEntryDistanceToTargetField);
        String dttString = dttField.getText().toString();
        logEntry.setDistanceToTarget(FormatUtility.fromNumericString(dttString));

        // set cutaway
        CheckBox caField = (CheckBox) getView().findViewById(R.id.LogEntryCutawayField);
        logEntry.setCutaway(caField.isChecked());
	}
	
	private void save()
	{       
		commitChangesToLogEntry();
		
		// save
		if (isEdit)
		{
			repository.updateLogEntry(logEntry);
		}
		else
		{
			repository.addLogEntry(logEntry);
		}
		
		fileManager.deleteUnusedImageFiles();
	}
	
	private void delete()
	{
		// delete log entry
		repository.deleteLogEntry(logEntry);
		
		close();
	}
	
	private void showSaveWarning()
	{
		// create alert dialog
		AlertDialog.Builder builder = new AlertDialog.Builder(
				new ContextThemeWrapper(getActivity(), R.style.DialogStyle));
		builder.setMessage(R.string.log_entry_save_warning);
		builder.setIcon(android.R.drawable.ic_dialog_alert);
		builder.setTitle(R.string.save_confirmation);
		builder.setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				save();
				saveWarningReply(true);
			}
		});
		builder.setNeutralButton(R.string.no_button, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				saveWarningReply(true);
			}
		});
		builder.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				saveWarningReply(false);
			}
		});
			
		AlertDialog dialog = builder.create();
		// show dialog
		dialog.show();
	}

	private void updateJumpNumber(int jumpNumber)
	{
		// update log entry
		logEntry.setJumpNumber(jumpNumber);
		
		// update ui
		TextView jnField = (TextView) getView().findViewById(R.id.LogEntryJumpNumberField);
		jnField.setText(FormatUtility.toNumericString(logEntry.getJumpNumber()));
	}
	
	private void showDeleteWarning()
	{
		// create alert dialog
		AlertDialog.Builder builder = new AlertDialog.Builder(
				new ContextThemeWrapper(getActivity(), R.style.DialogStyle));
		builder.setMessage(R.string.log_entry_delete_warning);
		builder.setIcon(android.R.drawable.ic_dialog_alert);
		builder.setTitle(R.string.delete_confirmation);
		builder.setPositiveButton(R.string.yes_button, deleteConfirmListener);
		builder.setNegativeButton(R.string.no_button, null);
		AlertDialog dialog = builder.create();
		// show dialog
		dialog.show();
	}
	
	private void showDateDialog()
	{
		// create date dialog
		Calendar cal = Calendar.getInstance();
		cal.setTime(logEntry.getDate());
		DatePickerDialog dialog = new DatePickerDialog(
				new ContextThemeWrapper(getActivity(), R.style.DialogStyle),
				dateSetListener,
				cal.get(Calendar.YEAR),
				cal.get(Calendar.MONTH),
				cal.get(Calendar.DAY_OF_MONTH));
		// show dialog
		dialog.show();
	}
	
	private void updateDate(Date date) 
	{
		// update log entry
		logEntry.setDate(date);
		
		// update ui
		TextView dateField = (TextView) getView().findViewById(R.id.LogEntryDateField);
		dateField.setText(FormatUtility.toDateString(getActivity(), logEntry.getDate()));
	}

	public void updateLocation(int id)
	{
		// update log entry
        logEntry.setLocation(locRepository.getLocation(id));
	}
	
	public void updateNotes(String notes)
	{
		// update log entry
		logEntry.setNotes(notes);
	}

	private void updateAircraft(int id)
    {
	    // update log entry
	    logEntry.setAircraft(aircraftRepository.getAircraft(id));
    }

	public void updateRig(List<Integer> ids)
	{
		// update log entry
        logEntry.getRigs().clear();
        logEntry.getRigs().addAll(rigRepository.getRigs(ids));
	}
	
	private void updateSkydiveType(int id)
    {
		// update log entry
		logEntry.setSkydiveType(skydiveTypeRepository.getSkydiveType(id));
    }
	
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    	inflater.inflate(R.menu.menu_save, menu);
        if (isEdit)
        	inflater.inflate(R.menu.menu_delete, menu);

        inflater.inflate(R.menu.menu_back, menu);
    }
    
    @Override
    public void onPrepareOptionsMenu(Menu menu)
    {
    	menu.findItem(R.id.menu_back).setVisible(isDualDisplay);
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        
		if (itemId == R.id.menu_save)
		{
			save();
			close();
			return true;
		}
		else if (itemId == R.id.menu_back)
		{
			if (isUpdated || checkForChanges() || !isEdit)
			{
				requestedAction = REQUEST_CLOSE;
				showSaveWarning();
				return true;
			}
			close();
			return true;
		}
		else if (itemId == R.id.menu_delete)
		{
			showDeleteWarning();
			return true;
		}
		else
		{
			return super.onOptionsItemSelected(item);
		}
    }
    
    public void updateContent(Bundle extras)
    {
    	loadData(extras);
    	updateFields();
    	initImagesUI();
    }
    
    @Override
    public void onSaveInstanceState (Bundle outState) {
        super.onSaveInstanceState(outState);
        
        configureBundle(outState);
    }
    
    public Bundle configureBundle(Bundle args)
    {
    	((SkydiveApplication) getActivity().getApplication()).storeLogEntry(logEntry);
    	args.putBoolean(Constants.EXTRA_LOG_ENTRY_SAVED, true);
    	
        if (isEdit)
        	args.putInt(Constants.EXTRA_LOG_ENTRY_ID, logEntryId);
    	
    	if (isUpdated)
    		args.putBoolean(Constants.EXTRA_LOG_ENTRY_UPDATED, true);
    	
		return args;
    }
    
    public Boolean requestUpdate()
    {
    	if (isUpdated || checkForChanges() || !isEdit)
    	{
    		requestedAction = REQUEST_UPDATE;
    		showSaveWarning();
    		return false;
    	}
    	
    	return true;
    }
    
    public Boolean requestClose()
    {
    	if (requestedAction == 0)
		{
    		requestedAction = REQUEST_CLOSE;
    		
    		if (isUpdated || checkForChanges() || !isEdit)
    		{
				showSaveWarning();
				return true;
			}		
		}
		
		close();
        return true;
    }
    
    private void saveWarningReply(Boolean reply)
    {
    	if (reply)
    	{
    		if (requestedAction == REQUEST_CLOSE)
    			close();
    		
    		else if (requestedAction == REQUEST_UPDATE)
    		{
    			mListener.onLogEntryEditStatusChanged(REPLY_UPDATEABLE);
    		}
    	}
    	else
    	{
    		requestedAction = 0;
    	}
    }
    
    private void close()
    {
    	mListener.onLogEntryEditStatusChanged(REPLY_CLOSED);
    	getFragmentManager().popBackStack();
    }
}